#ifndef _COMM_HPP_
#define _COMM_HPP_

#include<iostream>
#include<stdio.h>
#include<string>
#include<cassert>
#include<cerrno>
#include<cstring>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>


//这个文件目的是两个进程获得同一个key值
#define PATHNAME "." //这个名字取什么都行
#define PROJ_ID 0x66 //一样
// 共享内存的大小，一般建议是4KB的整数倍
// 系统分配共享内存是以4KB为单位的！ -- 内存划分内存块的基本单位
#define MAX_SIZE 4096 //字节  // --- 内核给你的会向上取整，内核给你的，和你能用的，是两码事
#define NAME_PIPE "/tmp/mypipe"  //命名管道路径

key_t getKey()
{
    key_t k = ftok(PATHNAME,PROJ_ID);
    if(k < 0)
    {
        //cin,cout,cerr -> stdin,stdout,stderr -> 0,1,2
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        exit(1);
    }
    return k;
}


int getShmHelper(key_t k,int flags)
{
    //k是要shmget，设置进入共享内存属性中的！
    //该共享内存，在内核中的唯一性！

    // shmid vs key:
    //   fd  vs inode
    int shmid = shmget(k,MAX_SIZE,flags);
    if(shmid < 0)
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        //如果共享内存都创建失败了，进程已经不能通信了，那我就直接退出
        exit(1);
    }
    return shmid;
}

int getShm(key_t k)//获取共享内存
{
    return getShmHelper(k,IPC_CREAT/*0*/);
}

int createShm(key_t k)//创建共享内存，一定是一个全新的Shm！
{
    return getShmHelper(k,IPC_CREAT | IPC_EXCL | 0600);
}

void* attchShm(int shmid)
{
    // 100;// 字面值
    // 10u;
    // 10L;
    // 3.14f;
    void* mem = shmat(shmid,nullptr,0); //64系统，8字节
    if((long long)mem == -1L)
    {
        std::cerr << "shmat" << errno << ":" << strerror(errno) << std::endl;
        exit(3);
    }
    return mem;
}

//detach:分离
void detachShm(void* start)
{
    if(shmdt(start) == -1)
    {
        std::cerr << "shmdt" << errno << ":" << strerror(errno) << std::endl;
    }
}

void delShm(int shmid)
{
    if(shmctl(shmid,IPC_RMID,nullptr) == -1)
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
    }
}

#endif